/*
 *  Copright: 2008 Philipp Leitner, Distributed Systems Group,
 *            TU Wien, leitner@infosys.tuwien.ac.at
 *
 *  This file is part of DAIOS.
 *
 *  DAIOS is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as
 *  published by the Free Software Foundation.
 * 
 *  DAIOS is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with DAIOS.  If not, see
 *  <http://www.gnu.org/licenses/>.
 * 
 */

package at.ac.tuwien.infosys.dsg.daios.framework;

import java.io.IOException;
import java.net.URL;
import java.util.logging.Logger;

import javax.wsdl.WSDLException;
import javax.xml.stream.XMLStreamException;

import at.ac.tuwien.infosys.dsg.daios.exceptions.AmbigiousException;
import at.ac.tuwien.infosys.dsg.daios.framework.interfaces.IConstants;

/**
 * 
 * Abstract factory class that should be utilized by clients to
 * create concrete factories for service invokers.
 * 
 * <p>
 * 
 * Implements the <i>Factory Method</i> pattern of GoF.
 * 
 * @author philipp
 *
 */
public abstract class ServiceFrontendFactory {
	
	// the logger
	private static Logger log = Logger.getLogger(IConstants.LOG_NAME);
	
	/**
	 * Create a new invoker. Has to be implemented by the
	 * concrete subclassses.
	 * 
	 * @param url The location of the WSDL definition file.
	 * @return The newly instantiated invoker.
	 * @throws WSDLException If an error occurs while retrieving or
	 * parsing the WSDL definition.
	 * @throws AmbigiousException 
	 * @throws XMLStreamException 
	 * @throws IOException 
	 */
	public abstract ServiceFrontend createFrontend(URL url)
		throws WSDLException, AmbigiousException, XMLStreamException, IOException;

	/**
	 * Create a new invoker. Has to be implemented by the
	 * concrete subclassses.
	 * 
	 * <p>
	 * 
	 * Note that this method is slightly faster than the
	 * version without setting the protocol type explicitly
	 * since this version does not need to figure the protocol
	 * out itself.
	 * 
	 * @param url The location of the WSDL definition file.
	 * @param protocol The Web Service procotol to use (SOAP or
	 * REST)
	 * @return The newly instantiated invoker.
	 * @throws WSDLException If an error occurs while retrieving or
	 * parsing the WSDL definition.
	 * @throws AmbigiousException 
	 * @throws XMLStreamException 
	 * @throws IOException 
	 */
	public abstract ServiceFrontend createFrontend(URL url, String protocol)
		throws WSDLException, AmbigiousException, XMLStreamException, IOException;
	
	/**
	 * Create a new invoker that is not linked to any interface
	 * or example (i.e. it has to be a REST GET invocation).
	 * 
	 * <p>
	 * 
	 * The exceptions thrown in this method are thrown only for
	 * compatiblity with createFrontend(URL url); these exceptions
	 * will not happen and can be ignored.
	 * 
	 * @return The newly instantiated invoker.
	 * @throws IOException
	 * @throws AmbigiousException 
	 * @throws WSDLException 
	 */
	public abstract ServiceFrontend createFrontend()
		throws WSDLException, AmbigiousException, IOException;
	
	/**
	 * Create a new invoker, and hook an interceptor for this
	 * invoker. Has to be implemented by the concrete subclassses.
	 * 
	 * <p>
	 * 
	 * Note that this method is slightly faster than the
	 * version without setting the protocol type explicitly
	 * since this version does not need to figure the protocol
	 * out itself.
	 * 
	 * @param url The location of the WSDL definition file.
	 * @param protocol The Web Service procotol to use (SOAP or
	 * REST)
	 * @param interceptor The interceptor that should be hooked
	 * into the frontend.
	 * @return The newly instantiated invoker.
	 * @throws WSDLException If an error occurs while retrieving or
	 * parsing the WSDL definition.
	 * @throws AmbigiousException 
	 * @throws XMLStreamException 
	 * @throws IOException 
	 */	
	public abstract ServiceFrontend createFrontend(URL url, String protocol,
		DaiosInterceptor interceptor)
		throws WSDLException, AmbigiousException, XMLStreamException, IOException;	

	/**
	 * Create a new invoker that is not linked to any interface
	 * or example (i.e. it has to be a REST GET invocation), and
	 * hook an interceptor for this invoker.
	 * 
	 * <p>
	 * 
	 * The exceptions thrown in this method are thrown only for
	 * compatiblity with createFrontend(URL url); these exceptions
	 * will not happen and can be ignored.
	 * 
	 * @param interceptor The interceptor to hook into the frontend.
	 * @return The newly instantiated invoker.
	 * @throws IOException
	 * @throws AmbigiousException 
	 * @throws WSDLException 
	 */
	public abstract ServiceFrontend createFrontend(DaiosInterceptor interceptor)
		throws WSDLException, AmbigiousException, IOException;	
	
	/**
	 * Static factory method to fetch a given conrete subclass to a
	 * String name. Should <i>not</i> be overidden or used by subclasses.
	 * 
	 * @param type The full qualified class name of the concrete subclass.
	 * @return A new Factory of the given type.
	 */
	public static ServiceFrontendFactory getFactory(String type) {
		
		ServiceFrontendFactory factory = null;
		
		try {
			
			Class fac = Class.forName(type);
			
			log.info("Creating factory of type "+fac.getCanonicalName());
			factory = (ServiceFrontendFactory) fac.newInstance();
			
		} catch (ClassNotFoundException e) {
			log.severe("Factory class not found: "+type);
			e.printStackTrace();
		} catch (InstantiationException e) {
			log.severe("Cannot instantiate new Service Frontend.");
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			log.severe("Error while creating factory.");
			e.printStackTrace();
		}
		
		return factory;
		
	}
	
}
